define([
    'mbTerrainLayer',
    'mbElevationUtils',
    'mbMarkerUtils',
    'three.effectComposer',
], function (mbTerrain, mbElevationUtils, mbMarkerUtils) {
    return function initTerrain(map, gl) {

        var DEBUG_LOW_POWER = true;

        // var mbmaputils = window.mbmap;
        var MBTerrainLayer = mbTerrain.MBTerrainLayer;
        var makeClipmapMesh = mbTerrain.makeClipmapMesh;

        var $ = function (a) {
            return document.querySelector(a)
        };

        var terrainObject = new MBTerrainLayer({
            allowPlaceholder: false,
            useShaderPass: false,
            shellOnly: true,
            getZoom: function () {
                return map.getZoom();
            },
            getBoundPolygon: function () {
                var width = map.getCanvas().width;
                var height = map.getCanvas().height;
                /*
                 * extend by 1 tile size
                 */
                var p0 = map.unproject([0, 0]);
                var p1 = map.unproject([width, 0]);
                var p2 = map.unproject([width, height]);
                var p3 = map.unproject([0, height]);
                return [
                    [p0.lng, p0.lat],
                    [p1.lng, p1.lat],
                    [p2.lng, p2.lat],
                    [p3.lng, p3.lat],
                    [p0.lng, p0.lat],
                ];
            },
            renderOpts: {
                canvas: map.getCanvas(),
                autoClear: true,
                powerPreference: DEBUG_LOW_POWER ? 'low-power' : 'default',
                logarithmicDepthBuffer: true,
            },
        });

        // terrainObject.renderer.autoClear = false;
        terrainObject.renderer.autoClearColor = false;
        terrainObject.renderer.setClearAlpha(0);
        terrainObject.renderer.setClearColor(0xffffff);
        terrainObject.controls.enabled = false;
        terrainObject.renderer.setPixelRatio(window.devicePixelRatio || 1);

        var shown = true;
        terrainObject.toggle = function (s) {
            if (s !== undefined) {
                shown = s;
            }
            if (shown) {
                map.setLayoutProperty('terrain3d', 'visibility', 'none');
            } else {
                map.setLayoutProperty('terrain3d', 'visibility', 'visible');
            }
            shown = !shown;
        };

        window.terrainObject = terrainObject;

        var terrainLayerId = 'terrain3d';

        if (map.setTerrain) {
            map.addSource('mapbox-dem', {
                'type': 'raster-dem',
                'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
                'tileSize': 512,
                'maxzoom': 14
            });
            map.setTerrain({'source': 'mapbox-dem', 'exaggeration': 2});
        }

        var terrainLayer = {
            id: terrainLayerId,
            type: 'custom',
            renderingMode: '3d',
            onAdd: function (bmap, gl) {
            },
            render: function (gl, matrix) {
                gl.clear(gl.DEPTH_BUFFER_BIT);
                // map.triggerRepaint();
                terrainObject.renderer.state.reset();
                terrainObject.renderInMbmap(map, gl, matrix);
            },
        };

        map.addLayer(terrainLayer);

        map.on('resize', function () {
            // canvas.width/height: rendered as (might be multiplied by devicePixelRatio)
            var canvas = map.getCanvas();
            var w = jQuery(canvas).width();
            var h = jQuery(canvas).height();
            terrainObject.resizeTo(w, h);
        });


        if (map.setTerrain) {
            terrainObject.toggle();
        }

        var tileSet = new mbElevationUtils.TileSet();

        var queryZoom = 15;


        /*
         * 128x128: cost 2G gpu mem
         */

        window.clipMesh = makeClipmapMesh({
            withWireframe: false,
            withSeams: false,
            demTileExtraZoom: 3, // for z >= (demTileExtraZoom+2), load textures at (zoom), load dem textures at (zoom - demTileExtraZoom)
            geometrySegments: 32, // total verts will be 200(tile) * (segments+1)*(segments+1) (vert), for 32x32, is 200k verts
            dynamicIncrementalZoom: 1, // show geometries at mapZoom + dynamicIncrementalZoom
            initZoom: map.getZoom(),
        });
        terrainObject.scene.add(clipMesh);

        terrainObject.onRendered = function (wgs, gcj) {
            clipMesh.applyCameraTarget(map, wgs, gcj);
        };

        var cen = map.getCenter();
        var lng = cen.lng, lat = cen.lat;
        tileSet.readElevationDataAtWgs(lng, lat, queryZoom, function (elev) {
            map.setBaseElevation(elev * 0.4);
            clipMesh.setBaseElevation(elev * 0.4);
        });


    };
});